<?php
class AnnotationHandler implements ReflectionHandler
{
	private $matchExp    = "/^[^\"\']+#\s{0,}@(.*\(.*\))[^\"\']+$/";
	private $bodyExp     = "/(\D+)\((\D+=.*\,{0,})\)/";
	private $valuesExp   = "/(\D+)=(.*)/";

	private $handlerName = "annotation";

	/**
	 * Ejecuta un controlador de reflección, el cual recibirá
	 * la línea de código que se encargará de parsear.
	 *
	 * @param $line Línea de código.
	 * @return Devuelve un objeto de reflection asociado a este controlador.
	 */
	public function execute( $line )
	{
		$match  = array();
		$body   = array();

		preg_match( $this->matchExp, " $line ", $match );

		// Verifica que la anotación se haya recuperado correctamente.
		//
		if ( !isset( $match[1] ) ) {
			return( null );
		}

		preg_match( $this->bodyExp, " ". $match[1] . " ", $body );

		// Verifica que exista el nombre de la clase Annotation.
		//
		if ( !isset( $body[1] ) ) {
			return( null );
		}

		$class = trim( $body[1] );

		// Verifica que la clase Annotation exista.
		//
		if ( !class_exists( $class ) ) {
			return( null );
		}

		$object = new $class(); // Crea la anotación.

		$object = $this->setObjectProperties( $object, $body );

		return( $object );
	}

	/**
	 * Verifica si la línea de código especificada podrá
	 * ser manipulada por este controlador de reflexión.
	 *
	 * @param $line Línea de código que se verificará.
	 * @return Si este controlador puede manejar la línea, devuelve
	 *         true, de lo contrario devuelve false.
	 */
	public function matchExpression( $line )
	{
		return (
			(preg_match( $this->matchExp, " $line " ) != false) ? true : false
		);
	}

	/**
	 * Devuelve el nombre del controlador.
	 */
	public function getHandlerName()
	{
		return( $this->handlerName );
	}

	private function setObjectProperties( $object, $body )
	{
		$props  = array();
		$values = array();

		// Obtiene la lista de propiedades.
		//
		$props = split( ",", $body[2] );

		for( $i = 0; $i < count($props); $i++ )
		{
			preg_match( $this->valuesExp, " ". $props[$i] . " ", $values );

			// Guarda eventualmente las propiedades que correspondan
			// al tipo de anotación que se creó.
			//
			if ( isset( $values[1] ) && isset( $values[2] ) )
			{
				$property = trim( $values[1] );

				if ( property_exists( $object, $property ) )
				{
					$value = str_replace( "\"", "", trim( $values[2] ) );

					$object->$property = $value;
				}
			}
		}

		return( $object );
	}
}
?>
